#include "snake.h"

// 游戏入口函数
void Snake::main(Screen &screen, Keys &keys) {
  initGame();
  gameState = MENU;

  while (true) {
    keys.kvs_update();

    switch (gameState) {
      case MENU:
        drawMenu(screen);
        if (keys.o.pressed()) {
          initGame();
          gameState = PLAYING;
          lastMoveTime = millis();
        } else if (keys.x.pressed()) {
          screen.spr.fillSprite(TFT_BLACK);
          screen.drawScreen();
          return;  // 返回上一级菜单
        }
        break;

      case PLAYING:
        handleInput(keys);
        if (millis() - lastMoveTime >= speed) {
          updateGame();
          lastMoveTime = millis();
        }
        drawGame(screen);

        if (keys.x.pressed()) {
          gameState = PAUSED;
        }
        break;

      case PAUSED:
        // 绘制暂停提示
        screen.spr.setTextDatum(CL_DATUM);
        screen.spr.setTextColor(TFT_YELLOW, TFT_BLACK);
        screen.spr.drawString("暂停", 80, 240, 4);
        screen.spr.drawString("O: 继续", 80, 280, 2);
        screen.spr.drawString("X: 退出", 80, 310, 2);
        screen.drawScreen();

        if (keys.o.pressed()) {
          gameState = PLAYING;
          lastMoveTime = millis();
        } else if (keys.x.pressed()) {
          freeSnake();
          screen.spr.fillSprite(TFT_BLACK);
          screen.drawScreen();
          return;
        }
        break;

      case GAME_OVER:
        drawGameOver(screen);
        if (keys.o.pressed()) {
          initGame();
          gameState = PLAYING;
          lastMoveTime = millis();
        } else if (keys.x.pressed()) {
          freeSnake();
          screen.spr.fillSprite(TFT_BLACK);
          screen.drawScreen();
          return;
        }
        break;
    }

    delay(10);
  }
}

// 初始化游戏
void Snake::initGame() {
  // 释放之前的蛇身
  freeSnake();

  // 初始化蛇头
  head = new SnakeNode();
  head->x = GRID_WIDTH / 2;
  head->y = GRID_HEIGHT / 2;
  head->next = nullptr;

  // 创建初始蛇身
  SnakeNode *current = head;
  for (int i = 1; i < INITIAL_LENGTH; i++) {
    SnakeNode *newNode = new SnakeNode();
    newNode->x = head->x - i;
    newNode->y = head->y;
    newNode->next = nullptr;
    current->next = newNode;
    current = newNode;
  }

  // 初始化方向和游戏参数
  currentDirection = RIGHT;
  nextDirection = RIGHT;
  score = 0;
  speed = INITIAL_SPEED;
  lastMoveTime = 0;

  // 生成第一个食物
  generateFood();
}

// 绘制菜单
void Snake::drawMenu(Screen &screen) {
  screen.spr.fillSprite(TFT_BLACK);
  screen.spr.setTextColor(TFT_GREEN, TFT_BLACK);
  screen.spr.setTextDatum(CC_DATUM);

  screen.spr.drawString("开始游戏", 120, 150, 4);
  screen.spr.setTextColor(TFT_WHITE, TFT_BLACK);
  screen.spr.drawString("O: 开始游戏", 120, 250, 2);
  screen.spr.drawString("X: 退出", 120, 280, 2);
  screen.spr.drawString("方向键: 移动", 120, 320, 2);

  screen.drawScreen();
}

// 绘制游戏画面
void Snake::drawGame(Screen &screen) {
  screen.spr.fillSprite(TFT_BLACK);

  // 绘制标题栏
  screen.spr.setTextColor(TFT_CYAN, TFT_BLACK);
  screen.spr.setTextDatum(TL_DATUM);
  screen.spr.drawString("分数: " + String(score), 5, 2, 2);
  screen.spr.drawString("长度: " + String(getSnakeLength()), 120, 2, 2);

  // 绘制游戏边界
  screen.spr.drawRect(GAME_AREA_X, GAME_AREA_Y, GRID_WIDTH * GRID_SIZE, GRID_HEIGHT * GRID_SIZE, TFT_DARKGREY);

  // 绘制食物
  screen.spr.fillRect(GAME_AREA_X + foodX * GRID_SIZE, GAME_AREA_Y + foodY * GRID_SIZE, GRID_SIZE, GRID_SIZE, TFT_RED);

  // 绘制蛇
  SnakeNode *current = head;
  bool isHead = true;
  while (current != nullptr) {
    uint16_t color = isHead ? TFT_YELLOW : TFT_GREEN;
    screen.spr.fillRect(GAME_AREA_X + current->x * GRID_SIZE, GAME_AREA_Y + current->y * GRID_SIZE, GRID_SIZE - 1, GRID_SIZE - 1, color);
    current = current->next;
    isHead = false;
  }

  screen.drawScreen();
}

// 绘制游戏结束画面
void Snake::drawGameOver(Screen &screen) {
  screen.spr.fillSprite(TFT_BLACK);
  screen.spr.setTextColor(TFT_RED, TFT_BLACK);
  screen.spr.setTextDatum(CC_DATUM);

  screen.spr.drawString("游戏结束", 120, 150, 4);
  screen.spr.setTextColor(TFT_WHITE, TFT_BLACK);
  screen.spr.drawString("分数: " + String(score), 120, 220, 4);
  screen.spr.drawString("长度: " + String(getSnakeLength()), 120, 260, 2);
  screen.spr.drawString("O: 重试", 120, 320, 2);
  screen.spr.drawString("X: 退出", 120, 350, 2);

  screen.drawScreen();
}

// 处理输入
void Snake::handleInput(Keys &keys) {
  // 更新方向,但不允许180度转向
  if (keys.up.pressed() && currentDirection != DOWN) {
    nextDirection = UP;
  } else if (keys.down.pressed() && currentDirection != UP) {
    nextDirection = DOWN;
  } else if (keys.left.pressed() && currentDirection != RIGHT) {
    nextDirection = LEFT;
  } else if (keys.right.pressed() && currentDirection != LEFT) {
    nextDirection = RIGHT;
  }
}

// 更新游戏状态
void Snake::updateGame() {
  currentDirection = nextDirection;
  moveSnake();

  // 检查碰撞
  if (checkCollision()) {
    gameState = GAME_OVER;
    return;
  }

  // 检查是否吃到食物
  if (checkFoodCollision()) {
    score += 10;
    growSnake();
    generateFood();

    // 增加速度(最快50ms)
    if (speed > 50) {
      speed = max(50, speed - 5);
    }
  }
}

// 移动蛇
void Snake::moveSnake() {
  // 计算新的头部位置
  int newX = head->x;
  int newY = head->y;

  switch (currentDirection) {
    case UP:
      newY--;
      break;
    case DOWN:
      newY++;
      break;
    case LEFT:
      newX--;
      break;
    case RIGHT:
      newX++;
      break;
  }

  // 创建新头部
  SnakeNode *newHead = new SnakeNode();
  newHead->x = newX;
  newHead->y = newY;
  newHead->next = head;
  head = newHead;

  // 删除尾部节点(除非吃到食物)
  SnakeNode *current = head;
  SnakeNode *prev = nullptr;
  while (current->next != nullptr) {
    prev = current;
    current = current->next;
  }
  if (prev != nullptr) {
    prev->next = nullptr;
    delete current;
  }
}

// 生成食物
void Snake::generateFood() {
  bool validPosition = false;

  while (!validPosition) {
    foodX = random(0, GRID_WIDTH);
    foodY = random(0, GRID_HEIGHT);

    // 检查食物是否在蛇身上
    validPosition = true;
    SnakeNode *current = head;
    while (current != nullptr) {
      if (current->x == foodX && current->y == foodY) {
        validPosition = false;
        break;
      }
      current = current->next;
    }
  }
}

// 检查碰撞
bool Snake::checkCollision() {
  // 检查是否撞墙
  if (head->x < 0 || head->x >= GRID_WIDTH || head->y < 0 || head->y >= GRID_HEIGHT) {
    return true;
  }

  // 检查是否撞到自己
  SnakeNode *current = head->next;
  while (current != nullptr) {
    if (head->x == current->x && head->y == current->y) {
      return true;
    }
    current = current->next;
  }

  return false;
}

// 检查是否吃到食物
bool Snake::checkFoodCollision() {
  return (head->x == foodX && head->y == foodY);
}

// 增长蛇身
void Snake::growSnake() {
  // 找到尾部
  SnakeNode *current = head;
  while (current->next != nullptr) {
    current = current->next;
  }

  // 在尾部添加新节点
  SnakeNode *newNode = new SnakeNode();
  newNode->x = current->x;
  newNode->y = current->y;
  newNode->next = nullptr;
  current->next = newNode;
}

// 释放蛇身内存
void Snake::freeSnake() {
  while (head != nullptr) {
    SnakeNode *temp = head;
    head = head->next;
    delete temp;
  }
}

// 获取蛇的长度
int Snake::getSnakeLength() {
  int length = 0;
  SnakeNode *current = head;
  while (current != nullptr) {
    length++;
    current = current->next;
  }
  return length;
}